package com.codeark.appengine.objectify;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.logging.Logger;

import com.google.common.base.Joiner;
import com.google.inject.AbstractModule;
import com.google.inject.BindingAnnotation;
import com.google.inject.Provides;
import com.google.inject.servlet.RequestScoped;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.ObjectifyOpts;


/**
 * an Objectify module
 * 
 * @author Yaniv Kessler (yaniv at codeark dot com)
 * 
 */
public class ObjectifyModule extends AbstractModule {

	private static final Logger log = Logger.getLogger(ObjectifyModule.class.getName());
	
	private static ObjectifyFactory ofy = new ObjectifyFactory();
	
	private ObjectifyOpts opts;

	public ObjectifyModule(Class<?>... persistentClasses) {
		this(null, persistentClasses);
	}

	public ObjectifyModule(ObjectifyOpts opts, Class<?>... persistentClasses) {
		this.opts = opts;
		
		ofy.getConversions().add(new JodaDateTimeConverter());
		log.info("registering " + JodaDateTimeConverter.class.getSimpleName());
		
		log.info("registering classes:" + Joiner.on(",").join(persistentClasses));
		
		for (Class<?> c : persistentClasses) 
			ofy.register(c);
		
	}
	
	@Override
	protected void configure() {
	}

	@Provides
	@RequestScoped
	protected Objectify providesObjectify() {
	
		if (opts != null)
			return ofy.begin(opts);

		return ofy.begin();
	}
	
	@Provides
	@RequestScoped
	@TransactionalObjectify
	protected Objectify providesTransactionalObjectify() {		
		return ofy.beginTransaction();
	}
	
	@BindingAnnotation
	@Retention(RetentionPolicy.RUNTIME)
	@Target( { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
	public @interface TransactionalObjectify {
	}	
}
